#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\src\iterator.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace STL_Impl_UnitTest
{

struct test_input_iterator : public stl::iterator
    <stl::input_iterator_tag, int>
{
    test_input_iterator(){value = 0; index = 0;}

    value_type value;
    difference_type index;
    reference operator *() {return value;}
    pointer operator ->() {return &operator*();}

    test_input_iterator& operator++(){++index; return *this;}
};

struct test_bidirectional_iterator : public stl::iterator
    <stl::bidirectional_iterator_tag, void*>
{
    test_bidirectional_iterator(){value = 0; index = 0;}

    value_type value;
    difference_type index;
    reference operator *() {return value;}
    pointer operator ->() {return &operator*();}

    test_bidirectional_iterator& operator++(){++index; return *this;}
    test_bidirectional_iterator& operator--(){--index; return *this;}

    test_bidirectional_iterator operator++(int)
    {
        auto temp = *this;
        operator++();
        return temp;
    }
    test_bidirectional_iterator operator--(int)
    {
        auto temp = *this;
        operator--();
        return temp;
    }
};

struct test_randomaccess_iterator : public stl::iterator
    <stl::random_access_iterator_tag, char>
{
    test_randomaccess_iterator(){value = 0; index = 0;}

    value_type value;
    difference_type index;
    reference operator *() {return value;}
    pointer operator ->() {return &operator*();}

    test_randomaccess_iterator& operator++(){++index; return *this;}
    test_randomaccess_iterator& operator--(){--index; return *this;}

    test_randomaccess_iterator operator++(int)
    {
        auto temp = *this;
        operator++();
        return temp;
    }
    test_randomaccess_iterator operator--(int)
    {
        auto temp = *this;
        operator--();
        return temp;
    }

    test_randomaccess_iterator operator-(difference_type n){index -= n; return *this;}
    test_randomaccess_iterator operator+(difference_type n){index += n; return *this;}
    test_randomaccess_iterator& operator-=(difference_type n){index -= n; return *this;}
    test_randomaccess_iterator& operator+=(difference_type n){index += n; return *this;}
};

TEST_CLASS(iterator_unittest)
{
public:
		
TEST_METHOD(unittest_advance)
{
	//InputIterator
    test_input_iterator it;
    stl::advance(it, 2);
    Assert::AreEqual(it.index, 2);

    test_bidirectional_iterator bidirectional_it;
    stl::advance(bidirectional_it, 4);
    Assert::AreEqual(bidirectional_it.index, 4);
    stl::advance(bidirectional_it, -3);
    Assert::AreEqual(bidirectional_it.index, 1);

    test_randomaccess_iterator ra_it;
    stl::advance(ra_it, 9);
    Assert::AreEqual(ra_it.index, 9);
}

};
}